﻿using System;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Media.Imaging;
using System.Xml.Linq;

using Perseus.Xml;

using Hetymine.Executioner.Commands;


namespace Hetymine.Executioner.Plugins.FTP {
    public class FTPCommand : ICommand {
        private static FTPCommandConfig _Configurator;

        private string _Host;

        public FTPCommand() {
            this.Name = string.Empty;
            this.Host = string.Empty;
            this.RootDirectory = string.Empty;
            this.FileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
                    Path.DirectorySeparatorChar;
            this.Username = string.Empty;
            this.Password = string.Empty;
            this.Passive = false;
            this.Copy = false;
        }        

        public string Host {
            get { return this._Host; }
            set {
                if (value.Length > 6 && value.Substring(0, 6) == "ftp://") {
                    value = value.Substring(6);
                }
                if (!value.EndsWith("/")) {
                    value += "/";
                }
                this._Host = value;
            }
        }
        public string RootDirectory { get; set; }
        public string FileDirectory { get; set; }
        public string Username { get; set; }
        public string Password { get; set; }
        public bool Passive { get; set; }
        public bool Copy { get; set; }

        public string Name { get; set; }        
        public bool Execute(string parameters) {
            string file;

            string[] prams = parameters.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);

            if (prams.Length == 0 || prams[0] == "-c") {
                string cname;                
                if (Clipboard.ContainsImage()) {
                    if (prams.Length >= 1) {
                        cname = prams[1];
                    }
                    else {
                        cname = Executioner.Config.GetString("Plugins.FTP", "Default Image Filename", "clipboard");
                    }

                    file = AppDomain.CurrentDomain.BaseDirectory +
                        "plugins" + Path.DirectorySeparatorChar +
                        "FTP" + Path.DirectorySeparatorChar +
                        cname + ".png";

                    string tmpFile = Path.GetTempFileName();
                    FileStream fs = new FileStream(tmpFile, FileMode.Create, FileAccess.Write);
                    try {
                        BitmapSource image = Clipboard.GetImage();
                        BmpBitmapEncoder bbe = new BmpBitmapEncoder();
                        bbe.Frames.Add(BitmapFrame.Create(image));
                        bbe.Save(fs);
                        fs.Close();

                        Uri uri = new Uri(tmpFile);
                        using (fs = new FileStream(file, FileMode.Create, FileAccess.Write)) {
                            PngBitmapEncoder pbe = new PngBitmapEncoder();
                            pbe.Interlace = PngInterlaceOption.Off;
                            pbe.Frames.Add(BitmapFrame.Create(uri));
                            pbe.Save(fs);
                        }                        
                    }
                    catch {
                        System.Media.SystemSounds.Beep.Play();
                        System.Media.SystemSounds.Beep.Play();
                        fs.Close();
                        return false;
                    }
                }
                else if (Clipboard.ContainsText()) {
                    if (prams.Length >= 1) {
                        cname = prams[1];
                    }
                    else {
                        cname = Executioner.Config.GetString("Plugins.FTP", "Default Text Filename", "clipboard");
                    }
                    file = AppDomain.CurrentDomain.BaseDirectory +
                        "plugins" + Path.DirectorySeparatorChar +
                        "FTP" + Path.DirectorySeparatorChar + 
                        cname + ".txt";                        

                    StreamWriter sw = new StreamWriter(file);
                    try {
                        sw.Write(Clipboard.GetText());
                        sw.Close();
                    }
                    catch {
                        System.Media.SystemSounds.Beep.Play();
                        sw.Close();
                        return false;
                    }
                }
                else { // Unknown type
                    System.Media.SystemSounds.Beep.Play();
                    return false;
                }
            }
            else {
                if (Path.IsPathRooted(parameters)) {
                    file = parameters;
                }
                else {
                    file = this.FileDirectory + parameters;
                }

                if (!File.Exists(file)) {
                    System.Media.SystemSounds.Beep.Play();
                    return false;
                }
            }

            string host = this.Host.Replace("{ROOT}", this.RootDirectory);

            string name = Path.GetFileName(file);
            FtpWebRequest request = (FtpWebRequest)FtpWebRequest.Create("ftp://" + host + name);
            request.Method = WebRequestMethods.Ftp.UploadFile;
            request.Credentials = new NetworkCredential(this.Username, this.Password);
            request.UsePassive = this.Passive;
            request.UseBinary = true;
            request.KeepAlive = false;

            int bytes;
            byte[] buffer = new byte[512];

            FileStream fileStream = new FileStream(file, FileMode.Open);
            Stream requestStream = request.GetRequestStream();

            while ((bytes = fileStream.Read(buffer, 0, buffer.Length)) > 0) {
                requestStream.Write(buffer, 0, bytes);
            }

            requestStream.Close();
            fileStream.Close();

            if (this.Copy) {
                System.Windows.Clipboard.SetText("http://" + this.Url + name);
            }

            return true;
        }

        private string Url {
            get {
                string url;

                if (this.Host.Contains("/{ROOT}/")) {
                    url = this.Host.Replace("{ROOT}/", string.Empty);
                }
                else {
                    url = this.Host.Replace("{ROOT}", string.Empty);
                }

                if (url.StartsWith("ftp.")) {
                    url = url.Substring(4);
                }

                return url;
            }
        }

        public void Load(XElement element) {
            this.Name = element.Element("Name").ValueOrEmpty();
            this.Host = element.Element("Host").ValueOrEmpty();
            this.RootDirectory = element.Element("RootDirectory").ValueOrEmpty();
            this.FileDirectory = element.Element("FileDirectory").ValueOrEmpty();
            if (this.FileDirectory == string.Empty) {
                this.FileDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) +
                    Path.DirectorySeparatorChar;
            }
            this.Username = element.Element("Username").ValueOrEmpty();
            this.Password = element.Element("Password").ValueOrEmpty();
            this.Passive = element.Attribute("Passive").ValueOrFalse();
            this.Copy = element.Attribute("Copy").ValueOrFalse();
        }
        public XElement Save() {
            if (this.IsEmpty) {
                throw new Exception("Cannot save empty hot string.");
            }

            XElement xe = new XElement("Plugin.FTP");            
            if (this.Passive) {
                xe.Add(new XAttribute("Passive", "true"));
            }
            if (this.Copy) {
                xe.Add(new XAttribute("Copy", "true"));
            }

            xe.Add(new XElement("Name", this.Name));
            xe.Add(new XElement("Host", this.Host));

            if (this.RootDirectory != string.Empty) {
                xe.Add(new XElement("RootDirectory", this.RootDirectory));
            }
            if (this.Username != string.Empty) {
                xe.Add(new XElement("Username", this.Username));
                xe.Add(new XElement("Password", this.Password));
            }
            if (this.FileDirectory != string.Empty) {
                xe.Add(new XElement("FileDirectory", this.FileDirectory));
            }            

            return xe;
        }
        public bool IsEmpty {
            get {
                if (this.Name.Trim() == string.Empty || this.Host.Trim() == string.Empty) {
                    return true;
                }

                return false;
            }
        }

        public ICommandConfigurator<ICommand> Configurator {
            get {
                if (FTPCommand._Configurator == null) {
                    FTPCommand._Configurator = new FTPCommandConfig();
                }
                FTPCommand._Configurator.InitializeConfig(this);
                return FTPCommand._Configurator;
            }
        }

        public override string ToString() {
            return this.Name + " (" + this.Url + ")";            
        }

        public object Clone() {
            FTPCommand ftpc = (FTPCommand)this.MemberwiseClone();

            return ftpc;
        }
    }
}
